''''''''''''''''''''''''''''''''''''''''''''''
' Enventory
'
' vbscript toolset to support administration, Enventory and control of AD Users and PC assets
'
' Copyright (C) ' by ufe@gmx.de
' started  July/August 2008, 
' based on work done within ::
'''''''''''''''''''''''''''''''''''
' Open Audit                  '
' http://open-audit.org	      '
' Software and Hardware Enventory '
' Outputs into MySQL          '
' (c) Mark Unwin 2003         '
'''''''''''''''''''''''''''''''''''
'
' This program is free software; you can redistribute it and/or modify
' it under the terms of the GNU General Public License as published by
' the Free Software Foundation; either version 2 of the License, or
' (at your option) any later version.

' This program is distributed in the hope that it will be useful,
' but WITHOUT ANY WARRANTY; without even the implied warranty of
' MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
' GNU General Public License for more details.

' You should have received a copy of the GNU General Public License along
' with this program; if not, write to the Free Software Foundation, Inc.,
' 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
'
Option Explicit

'  64bit workaround
'
' this script code relies on 32bit COM objects, if we are running on
' a 64bit system we will want to run under WOW64 (the x86 emulator).

'http://blogs.msdn.com/b/joshpoley/archive/2008/09/18/running-32bit-dependent-scripts-in-a-64bit-world.aspx

dim myHostShell

public function IS64()
	On Error Resume Next
	
	Dim WshShell
	Dim OsType

	Set WshShell = CreateObject("WScript.Shell")

	OsType = WshShell.RegRead("HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment\PROCESSOR_ARCHITECTURE")

	If OsType = "x86" then
		'wscript.excho "Windows 32bit system detected"
		IS64 = false
	elseif OsType = "AMD64" then
		'wscript.echo "Windows 64bit system detected"
		IS64 = true
	end if
end function

public function ISshell64()
	'On Error Resume Next
	
	Dim host
	host = WScript.FullName
	host = lcase(host)
	'wscript.echo "ISshell64 host:" & host
	if is64() then
	'	wscript.echo "is 64"
	'	wscript.echo InStr(1, host, "system32", vbTextCompare)
		if InStr(1, host, "system32", vbTextCompare) <> 0 then
	'		wscript.echo "64 bit - 64bit shell detected"
			ISshell64 = true
		else
	'	wscript.echo InStr(1, host, "syswow64", vbTextCompare) 
		if  InStr(1, host, "syswow64", vbTextCompare) <> 0 then 
	'			wscript.echo "64 bit - 32bit shell detected"
				ISshell64 = false
			end if
		end if
	else
	   ISshell64 = false
	end if
end function

public function WinDirGet()
	dim shell
	set shell = WScript.CreateObject("WScript.Shell")
	WinDirGet = shell.ExpandEnvironmentStrings("%windir%")
end function

public function ParameterGet()
	dim strArg
	Dim ArgObj
	Set ArgObj = WScript.Arguments
	'wScript.Echo WScript.Arguments.Count
	ParameterGet = ""
	For Each strArg in ArgObj
		ParameterGet = ParameterGet & " " & strArg
    next
end function  
	

' check to see if we are on an AMD64 processor and running the
' wrong version of the scripting host.

if IS64() then
	myHostShell = "64"
else
	myHostShell =  "32"
end if

if ISshell64() then
	myHostShell = myHostShell & "/shell64"
else
	myHostShell = myHostShell & "/shell32"
end if 
 
 
if ISshell64() then
    dim newcmd
	newcmd = windirget()&"\SysWoW64\cscript.exe " & WScript.ScriptFullName & ParameterGet()
	dim shell
	dim exec
	dim ret
	set shell = WScript.CreateObject("WScript.Shell")
   'WScript.Echo(myHostShell & " start")
	'wscript.echo newcmd
    ret = Shell.Run (newcmd, 0, true)
	'WScript.Echo(myHostShell & " end")
	
    WScript.Quit(ret)
 end if
' the real script code goes here ...


Public SuiteName : SuiteName = "E-nventory"
Public SuiteProg : SuiteProg = "SerialNumber"

Dim EnventoryLogDir
Dim EnventoryDataDir
Dim EmailFrom
Dim EmailTo
Dim DDEEVV
Dim DBhistoryDays
Dim DBhistoryUnique
Dim DBTablePerComputer
Dim DBTablePerOU 
Dim DBTableVersion : DBTableVersion = "0.6"
Dim DBPerApp
Dim RUNFrequence
Dim DBProvider

Dim DBFile

Dim WSHFileSignature

Dim EmailCc
Dim EmailServer
Dim EMailPort

Dim MyTypeMemo 
Dim MyTypeAutoincrement
Dim MyTablePrefix
Dim MyViewStatement
Dim MyAutoIndex
Dim MyAutoIndexGet

Dim  NtpServer

'' Below calls the config and tool files to setups.
'on error resume next
Dim sScriptPath
sScriptPath = Left(WScript.ScriptFullName, InStrRev(WScript.ScriptFullName, "\"))
ExecuteGlobal CreateObject("Scripting.FileSystemObject").OpenTextFile(sScriptPath & SuiteName & ".tools.vbs").ReadAll
If Err.Number <> 0 Then
			wscript.echo WScript.ScriptFullName & "::" & myScriptPath & SuiteName & ".tools.vbs " & Err.Number & " -- " &  Err.Description
			Err.Clear
End If
ExecuteGlobal CreateObject("Scripting.FileSystemObject").OpenTextFile(sScriptPath & SuiteName & ".tools-XML.vbs").ReadAll
If Err.Number <> 0 Then
			wscript.echo WScript.ScriptFullName & "::" & myScriptPath & SuiteName & ".tools.vbs " & Err.Number & " -- " &  Err.Description
			Err.Clear
End If
Dim myScriptNameExExt
Dim myScriptNameExExtExt
myScriptNameExExt=Left(WScript.ScriptFullName, InStrRev(WScript.ScriptFullName,".") -1)
myScriptNameExExtExt=Left(myScriptNameExExt,InStrRev(myScriptNameExExt,".")-1)
REM wscript.echo WScript.ScriptFullName & "::" & ("myScriptNameExExtExt " & myScriptNameExExtExt)
REM wscript.echo WScript.ScriptFullName & "::" & ("myScriptNameExExtExt " & myScriptNameExExtExt & ".conf.vbs")
REM wscript.echo WScript.ScriptFullName & "::" & ("hallo myScriptNameExExt >" & myScriptNameExExt & "<")
REM wscript.echo WScript.ScriptFullName & "::" & ("hallo myScriptNameExExt >" & myScriptNameExExt & ".conf.vbs<")


ExecuteGlobal CreateObject("Scripting.FileSystemObject").OpenTextFile(myScriptNameExExtExt & ".conf.vbs").ReadAll
If Err.Number <> 0 Then
			wscript.echo WScript.ScriptFullName & "::" & myScriptNameExExtExt & ".conf.vbs " & Err.Number & " -- " &  Err.Description
			Err.Clear
End If
ExecuteGlobal CreateObject("Scripting.FileSystemObject").OpenTextFile(myScriptNameExExt & ".conf.vbs").ReadAll
If Err.Number <> 0 Then
			wscript.echo WScript.ScriptFullName & "::" &  myScriptNameExExt & "<<.conf.vbs" & Err.Number & " -- " &  Err.Description
			Err.Clear
End If 

Call Main()

Sub Main ()
	if DDEEVV = true then On Error Goto 0 Else On Error Resume Next
	DIM rs
	Dim TableDef
	Dim TableColumns
	Dim TableValues

	ToolsTimerStart()

	Dbopen()

	mydebug("main " & myScriptNameExExt)
	
	Dim ComputerName : ComputerName = ComputerNameGet()
	Dim UserName : UserName = UserNameGet()
	dim TableData(8,2)
	dim TableWhere(1,2)
	
	'mydebug ("SerialPCGet")
	serialPCGet(ComputerName) 
	'mydebug ("SystemTypeGet")
	SystemTypeGet(ComputerName)
	'mydebug ("SystemTypeGet done")
	
	if myPCIdentifyingNumber <> "" then
		TableData (0,0) = "[ComputerName]" 		: TableData (0,1) = MyTypeMemo	: TableData (0,2) = ComputerName 
		TableData (1,0) = "[Device]" 			: TableData (1,1) = MyTypeMemo	: TableData (1,2) = "Computer"
		TableData (2,0) = "[Vendor]" 			: TableData (2,1) = MyTypeMemo	: TableData (2,2) = myPCVendor
		TableData (3,0) = "[Type]" 				: TableData (3,1) = MyTypeMemo	: TableData (3,2) = myPCType
		TableData (4,0) = "[Serial]" 			: TableData (4,1) = MyTypeMemo	: TableData (4,2) = myPCIdentifyingNumber
		TableData (5,0) = "[info]"				: TableData (5,1) = MyTypeMemo	: TableData (5,2) = "ChassisType " & myPCsystem_system_type
		TableData (6,0) = "" 					: TableData (6,1) = ""			: TableData (6,2) = ""
		
		TableWhere (0,0) = "[Serial]" 			: TableWhere (0,1) = MyTypeMemo	: TableWhere (0,2) = myPCIdentifyingNumber
		TableWhere (1,0) = "" 					: TableWhere (1,1) = ""			: TableWhere (1,2) = ""
		mydebug(  "Computer " & myPCVendor & " " & myPCType & " " & myPCIdentifyingNumber )
		logfilewrite(  "Computer " & myPCVendor & " " & myPCType & " " & myPCIdentifyingNumber )
		DBDoTableAr  DBGetTableName(""), DBTableVersion, TableData, TableWhere, DBhistoryUnique 
	else
		logfilewrite(  "Computer " & myPCVendor & " " & myPCType & " has not PCIdentifyingNumber !" )
	end if 
	GetMonitorInfo()
	DBClearHistory DBGetTableName(""), True
	LogFileWrite("DBTable2XML SerialNumbers" )		
	dim XMLfileObj
	set XMLfileObj =  XMLInit(computernameGet() )	
	DBTable2XML  XMLfileObj, "", "SELECT " & MyTablePrefix & "SerialNumber.* FROM " & MyTablePrefix & "SerialNumber WHERE " & _
			" (((" & MyTablePrefix & "SerialNumber.eComputer)='" & computernameGet() & "'));" 
	LogFileWrite("XMLWrite " & computernameGet()  )
	dim xmlfilename
	xmlfilename = XMLWrite (XMLfileObj,computernameGet() )
	LogFileWrite("XML SerialNumbers  done " )
	
	EventLogWrite EVENT_SUCCESS, WScript.ScriptFullName & " Execution Time: " & ToolsTimerGet()  & " seconds."
	logfileclose
End Sub


Dim myPCVendor
Dim myPCType
Dim myPCIdentifyingNumber
Dim myPCsystem_system_type

Function SerialPCGet(strComputer)
	mydebug ("SerialPCGet") 
	if DDEEVV = true then On Error Goto 0 Else On Error Resume Next
		Dim objNetwork
		Dim strComputerName
		Dim StrUsername
		Dim objWMIService
		Dim	colItems
		Dim objItem

		Set objNetwork = CreateObject("WScript.Network")
		strComputerName = objNetwork.Computername
		StrUsername = objNetwork.UserName
		
		Set objWMIService = GetObject("winmgmts:\\" & StrComputer & "\root\cimv2")
		
	    Set colItems = objWMIService.InstancesOf("Win32_ComputerSystemProduct",48)
		'TableColumns = "UserName;ComputerName;Vendor;Type;Serial;UUID"
		For Each objItem In colItems
			myPCVendor = Trim(objItem.Vendor)
			myPCType = Trim(objItem.Name)
			myPCIdentifyingNumber = Trim(objItem.IdentifyingNumber)
		Next
		'LogFileWrite(SerialSet)
end Function

Function SystemTypeGet(strComputer) 
	if DDEEVV = true then On Error Goto 0 Else On Error Resume Next
	Dim comment
	Dim objWMIService
	Dim objItem
	Dim colItems
	Dim system_model
	Dim system_name
	Dim system_num_processors
	Dim system_part_of_domain
	Dim system_primary_owner_name
	Dim domain_role
	Dim domain_role_text
	Dim system_system_type
	
	comment = "System Info"
	SystemTypeGet =  "'',''"
	'LogFileWrite(comment)
	if DDEEVV = true then On Error Goto 0 Else On Error Resume Next 
	Set objWMIService = GetObject("winmgmts:\\" & StrComputer & "\root\cimv2")
	Set colItems = objWMIService.ExecQuery("Select * from Win32_ComputerSystem",,48)
	For Each objItem In colItems
	   system_model = clean(objItem.Model)
	   system_name = clean(objItem.Name)
	   system_num_processors = clean(objItem.NumberOfProcessors)
	   system_part_of_domain = clean(objItem.PartOfDomain)
	   system_primary_owner_name = clean(objItem.PrimaryOwnerName)
	Next
	
	Set colItems = objWMIService.ExecQuery("Select * from Win32_SystemEnclosure",,48)
	For Each objItem In colItems
	   system_system_type = Join(objItem.ChassisTypes, ",")
	Next
	if system_system_type = "1" then system_system_type = "Other" End If
	if system_system_type = "2" then system_system_type = "Unknown" End If
	if system_system_type = "3" then system_system_type = "Desktop" End If
	if system_system_type = "4" then system_system_type = "Low Profile Desktop" End If
	if system_system_type = "5" then system_system_type = "Pizza Box" End If
	if system_system_type = "6" then system_system_type = "Mini Tower" End If
	if system_system_type = "7" then system_system_type = "Tower" End If
	if system_system_type = "8" then system_system_type = "Portable" End If
	if system_system_type = "9" then system_system_type = "Laptop" End If
	if system_system_type = "10" then system_system_type = "Notebook" End If
	if system_system_type = "11" then system_system_type = "Hand Held" End If
	if system_system_type = "12" then system_system_type = "Docking Station" End If
	if system_system_type = "13" then system_system_type = "All in One" End If
	if system_system_type = "14" then system_system_type = "Sub Notebook" End If
	if system_system_type = "15" then system_system_type = "Space-Saving" End If
	if system_system_type = "16" then system_system_type = "Lunch Box" End If
	if system_system_type = "17" then system_system_type = "Main System Chassis" End If
	if system_system_type = "18" then system_system_type = "Expansion Chassis" End If
	if system_system_type = "19" then system_system_type = "SubChassis" End If
	if system_system_type = "20" then system_system_type = "Bus Expansion Chassis" End If
	if system_system_type = "21" then system_system_type = "Peripheral Chassis" End If
	if system_system_type = "22" then system_system_type = "Storage Chassis" End If
	if system_system_type = "23" then system_system_type = "Rack Mount Chassis" End If
	if system_system_type = "24" then system_system_type = "Sealed-Case PC"  End If
	
	myPCsystem_system_type = system_system_type
	SystemTypeGet = system_system_type
	'LogFileWrite(SystemTypeSet)
	mydebug ("SystemTypeGet " & system_system_type)
End Function

Function GetMonitorInfo()
	dim arrAllDisplays
	dim arrAllMonitors
	dim arrActiveMonitors
	dim strFormattedMonitorInfo
	dim arrActiveEDID
	dim arrParsedMonitorInfo
				
	'mydebug "Getting all display devices"
	arrAllDisplays=GetAllDisplayDevicesInReg()
	'mydebug "Filtering display devices to monitors"
	arrAllMonitors=GetAllMonitorsFromAllDisplays(arrAllDisplays)
	'mydebug "Filtering monitors to active monitors"
	arrActiveMonitors=GetActiveMonitorsFromAllMonitors(arrAllMonitors)
	if ubound(arrActiveMonitors)=0 and arrActiveMonitors(0)="{ERROR}" then
		mydebug "No active monitors found"
		strFormattedMonitorInfo="[Monitor_1]" & vbcrlf & "Monitor=Not Found" & vbcrlf & vbcrlf
	else
		mydebug "Found active monitors"
		mydebug "Retrieving EDID for all active monitors"
		arrActiveEDID=GetEDIDFromActiveMonitors(arrActiveMonitors)
		mydebug "Parsing EDID/Windows data"
		arrParsedMonitorInfo=GetParsedMonitorInfo(arrActiveEDID,arrActiveMonitors)
		mydebug "Formatting parsed data"
		strFormattedMonitorInfo=MonitorInfo2DB(arrParsedMonitorInfo)
	end if
	mydebug "Data retrieval completed"
	GetMonitorInfo=strFormattedMonitorInfo
end function

Function MonitorInfo2DB(arrParsedMonitorInfo)
	dim tmpctr
	dim tmpOutput
	dim tmpResult
	dim TableData(8,2)
	dim TableWhere(1,2)
	Dim ComputerName : ComputerName = ComputerNameGet()
	
	for tmpctr=0 to ubound(arrParsedMonitorInfo)
		tmpResult=split(arrParsedMonitorInfo(tmpctr),"|||")
		tmpOutput=tmpOutput & "[Monitor_" & cstr(tmpctr+1) & "]" & vbcrlf
		tmpOutput=tmpOutput & "EDID_VESAManufacturerID=" & tmpResult(1) & vbcrlf
		tmpOutput=tmpOutput & "EDID_DeviceID=" & tmpResult(3) & vbcrlf
		tmpOutput=tmpOutput & "EDID_ManufactureDate=" & tmpResult(2) & vbcrlf
		tmpOutput=tmpOutput & "EDID_SerialNumber=" & tmpResult(0) & vbcrlf
		tmpOutput=tmpOutput & "EDID_ModelName=" & tmpResult(4) & vbcrlf
		tmpOutput=tmpOutput & "EDID_Version=" & tmpResult(5) & vbcrlf
		tmpOutput=tmpOutput & "Windows_VESAID=" & tmpResult(6) & vbcrlf
		tmpOutput=tmpOutput & "Windows_PNPID=" & tmpResult(7) & vbcrlf & vbcrlf
		if tmpResult(0) <> "Not Present in EDID" then
			TableData (0,0) = "[ComputerName]" 		: TableData (0,1) = MyTypeMemo	: TableData (0,2) = ComputerName 
			TableData (1,0) = "[Device]" 			: TableData (1,1) = MyTypeMemo	: TableData (1,2) = "Monitor"
			TableData (2,0) = "[Vendor]" 			: TableData (2,1) = MyTypeMemo	: TableData (2,2) = tmpResult(1) 
			TableData (3,0) = "[Type]" 				: TableData (3,1) = MyTypeMemo	: TableData (3,2) = tmpResult(4) 
			TableData (4,0) = "[Serial]" 			: TableData (4,1) = MyTypeMemo	: TableData (4,2) = tmpResult(0)
			TableData (5,0) = "[info]"				: TableData (5,1) = MyTypeMemo	: TableData (5,2) = "ManufactureDate "& tmpResult(2) 
			TableData (6,0) = "" 					: TableData (6,1) = ""			: TableData (6,2) = ""
			TableWhere (0,0) = "[Serial]" 			: TableWhere (0,1) = MyTypeMemo	: TableWhere (0,2) = tmpResult(0)
			TableWhere (1,0) = "" 					: TableWhere (1,1) = ""			: TableWhere (1,2) = ""
			mydebug("Monitor " & tmpResult(1) & " " &  tmpResult(4) & " " & tmpResult(0) )
			logfilewrite ("Monitor " & tmpResult(1) & " " &  tmpResult(4) & " " & tmpResult(0) )
			DBDoTableAr  DBGetTableName(""), DBTableVersion, TableData, TableWhere, DBhistoryUnique 
		end if
	next
	MonitorInfo2DB=tmpOutput
End Function

'****************************************
' Monitor EDID Information v1.2'
'coded by Michael Baird
'20-September-2005
'All code herein is copyleft 2005
'and is released under the terms of the GNU open source
'license agreement
'****************************************
'
'****************************************
'If you are trying to customize the output for your specific needs
'check the function named ""
'It is probably all you need to change
'****************************************
'
'****************************************
'This is a complete re-write of the script I originally relased 17-June-2004
'It should function much more reliably and work better with multiple monitors
'The code has been modularized and streamlined for easier readability and debugging
'several bugs have been eliminated.
'There was really no excuse for the sheer ugliness of the original code.
'I will only say that I was figuring it out as I went along and I was really tired
'because SWMBO was out of town and I tend to pull all-nighters when she's not around
'to resue me from my PC and myself.
'
'Please give me credit if you use my code
'Please don't profit financially from my code (at least not ridiculously)
'****************************************
'
'****************************************
'this code is based on the EEDID spec found at http://www.vesa.org
'and by my hacking around in the windows registry
'the code was tested on WINXP,WIN2K and WIN2K3
'it should work on WINME and WIN98SE
'It should work with multiple monitors, but that hasn't been tested either.
'****************************************
'
'****************************************
'It should be noted that this code is not 100% reliable (what is?)
'I have witnessed occasions where for one reason or another windows
'can't or doesn't read the EDID info at boot (example would be someone
'booting with the monitor turned off) and so windows changes the active
'monitor to "Default_Monitor"
'Another reason for reliability problems is that there is no
'requirement in the EDID spec that a manufacture include the
'serial number in the EDID data AND only EDIDv1.2 and beyond 
'have a requirement that the EDID contain a descriptive
'model name
'That being said, here goes....
'****************************************
'
'****************************************
'Some notes on the general function....
'
'Monitors are stored in HKLM\SYSTEM\CurrentControlSet\Enum\DISPLAY\
'
'Unfortunately, not only monitors are stored here Video Chipsets and maybe some other stuff
'is also here.
'
'Monitors in "HKLM\SYSTEM\CurrentControlSet\Enum\DISPLAY\" are organized like this:
' HKLM\SYSTEM\CurrentControlSet\Enum\DISPLAY\<VESA_Monitor_ID>\<PNP_ID>\
'Since not only monitors will be found under DISPLAY sub key you need to find out which
'devices are monitors.
'This can be deterimined by looking at the value "HardwareID" located
'at HKLM\SYSTEM\CurrentControlSet\Enum\DISPLAY\<VESA_Monitor_ID\<PNP_ID>\
'if the device is a monitor then the "HardwareID" value will contain the data "Monitor\<VESA_Monitor_ID>"
'
'The next difficulty is that all monitors are stored here not just the one curently plugged in.
'So, if you ever switched monitors the old one(s) will still be in the registry.
'You can tell which monitor(s) are active because they will have a sub-key named "Control"
'****************************************
'
'On with the code...
'
'DISPLAY_REGKEY sets the regkey where displays are found. Don't change except for debugging
'I only change it when I am looking at a .REG file that someone sent me saying that the
'code doesn't work.
Const DISPLAY_REGKEY="HKLM\SYSTEM\CurrentControlSet\Enum\DISPLAY\"
'sets the debug outfile (use format like c:\debug.txt)
Const DEBUGFILE="NUL"
'if set to 1 then output debug info to DEBUGFILE (also writes debug to screen if running under cscript.exe)
Const DEBUGMODE=0
'The ForceCscript subroutine forces execution under CSCRIPT.EXE/Prevents execution
'under WSCRIPT.EXE -- useful when debugging
'ForceCscript

'mydebug "Execution Started " & cstr(now)
'wscript.echo WScript.ScriptFullName & "::" & GetMonitorInfoOrg() 'just write the output to screen
'mydebug "Execution Completed " & cstr(now)

'This is the main function. It calls everything else
'in the correct order.
Function GetMonitorInfoOrg()
	dim arrAllDisplays
	dim arrAllMonitors
	dim arrActiveMonitors
	dim strFormattedMonitorInfo
	dim arrActiveEDID
	dim arrParsedMonitorInfo
			
	mydebug "Getting all display devices"
	arrAllDisplays=GetAllDisplayDevicesInReg()
	mydebug "Filtering display devices to monitors"
	arrAllMonitors=GetAllMonitorsFromAllDisplays(arrAllDisplays)
	mydebug "Filtering monitors to active monitors"
	arrActiveMonitors=GetActiveMonitorsFromAllMonitors(arrAllMonitors)
	if ubound(arrActiveMonitors)=0 and arrActiveMonitors(0)="{ERROR}" then
		mydebug "No active monitors found"
		strFormattedMonitorInfo="[Monitor_1]" & vbcrlf & "Monitor=Not Found" & vbcrlf & vbcrlf
	else
		mydebug "Found active monitors"
		mydebug "Retrieving EDID for all active monitors"
		arrActiveEDID=GetEDIDFromActiveMonitors(arrActiveMonitors)
		mydebug "Parsing EDID/Windows data"
		arrParsedMonitorInfo=GetParsedMonitorInfo(arrActiveEDID,arrActiveMonitors)
		mydebug "Formatting parsed data"
		strFormattedMonitorInfo=GetFormattedMonitorInfoOrg(arrParsedMonitorInfo)
	end if
	mydebug "Data retrieval completed"
	GetMonitorInfo=strFormattedMonitorInfo
end function

'this function formats the parsed array for display
'this is where the final output is generated
'it is the one you will most likely want to
'customize to suit your needs
Function GetFormattedMonitorInfoOrg(arrParsedMonitorInfo)
	dim tmpctr
	dim tmpOutput
	dim tmpResult
	
	for tmpctr=0 to ubound(arrParsedMonitorInfo)
		tmpResult=split(arrParsedMonitorInfo(tmpctr),"|||")
		tmpOutput=tmpOutput & "[Monitor_" & cstr(tmpctr+1) & "]" & vbcrlf
		tmpOutput=tmpOutput & "EDID_VESAManufacturerID=" & tmpResult(1) & vbcrlf
		tmpOutput=tmpOutput & "EDID_DeviceID=" & tmpResult(3) & vbcrlf
		tmpOutput=tmpOutput & "EDID_ManufactureDate=" & tmpResult(2) & vbcrlf
		tmpOutput=tmpOutput & "EDID_SerialNumber=" & tmpResult(0) & vbcrlf
		tmpOutput=tmpOutput & "EDID_ModelName=" & tmpResult(4) & vbcrlf
		tmpOutput=tmpOutput & "EDID_Version=" & tmpResult(5) & vbcrlf
		tmpOutput=tmpOutput & "Windows_VESAID=" & tmpResult(6) & vbcrlf
		tmpOutput=tmpOutput & "Windows_PNPID=" & tmpResult(7) & vbcrlf & vbcrlf
	next
	GetFormattedMonitorInfo=tmpOutput
End Function

'This function returns an array of all subkeys of the 
'regkey defined by DISPLAY_REGKEY
'(typically this should be "HKLM\SYSTEM\CurrentControlSet\Enum\DISPLAY")
Function GetAllDisplayDevicesInReg()
	dim arrResult()
	redim arrResult(0)
	dim intArrResultIndex
	dim arrtmpkeys
	dim tmpctr
	dim arrtmpkeys2
	dim tmpctr2
	
	intArrResultIndex=-1
	arrtmpkeys=RegEnumKeys(DISPLAY_REGKEY)
	if vartype(arrtmpkeys)<>8204 then
		arrResult(0)="{ERROR}"
		GetAllDisplayDevicesInReg=false
		mydebug "Display=Can't enum subkeys of display regkey"
	else
		for tmpctr=0 to ubound(arrtmpkeys)
			arrtmpkeys2=RegEnumKeys(DISPLAY_REGKEY & arrtmpkeys(tmpctr))
			for tmpctr2 = 0 to ubound(arrtmpkeys2)
				intArrResultIndex=intArrResultIndex+1
				redim preserve arrResult(intArrResultIndex)
				arrResult(intArrResultIndex)=DISPLAY_REGKEY & arrtmpkeys(tmpctr) & "\" & arrtmpkeys2(tmpctr2)
				'mydebug "Display=" & arrResult(intArrResultIndex)
			next 
		next
	end if
	GetAllDisplayDevicesInReg=arrResult
End Function

'This function is passed an array of regkeys as strings
'and returns an array containing only those that have a
'hardware id value appropriate to a monitor.
Function GetAllMonitorsFromAllDisplays(arrRegKeys)
	dim arrResult()
	redim arrResult(0)
	dim intArrResultIndex
	dim tmpctr
	
	intArrResultIndex=-1
	for tmpctr=0 to ubound(arrRegKeys)
		if IsDisplayDeviceAMonitor(arrRegKeys(tmpctr)) then
			intArrResultIndex=intArrResultIndex+1
			redim preserve arrResult(intArrResultIndex)
			arrResult(intArrResultIndex)=arrRegKeys(tmpctr)
			'mydebug "Monitor=" & arrResult(intArrResultIndex)
		end if
	next
	if intArrResultIndex=-1 then
		arrResult(0)="{ERROR}"
		mydebug "Monitor=Unable to locate any monitors"
	end if
	GetAllMonitorsFromAllDisplays=arrResult
End Function

'this function is passed a regsubkey as a string
'and determines if it is a monitor
'returns boolean
Function IsDisplayDeviceAMonitor(strDisplayRegKey)
	dim arrtmpResult
	dim strtmpResult
	
	arrtmpResult=RegGetMultiStringValue(strDisplayRegKey,"HardwareID")
	strtmpResult="|||" & join(arrtmpResult,"|||") & "|||"
	if instr(lcase(strtmpResult),"|||monitor\")=0 then
		'mydebug "MonitorCheck='" & strDisplayRegKey & "' is not a monitor"
		IsDisplayDeviceAMonitor=false
	else
		'mydebug "MonitorCheck='" & strDisplayRegKey & "' is a monitor"
		IsDisplayDeviceAMonitor=true
	end if
End Function

'This function is passed an array of regkeys as strings
'and returns an array containing only those that have a
'subkey named "Control"...establishing that they are current.
Function GetActiveMonitorsFromAllMonitors(arrRegKeys)
	dim arrResult()
	redim arrResult(0)
	dim intArrResultIndex
	dim tmpctr
	
	intArrResultIndex=-1
	for tmpctr=0 to ubound(arrRegKeys)
		if IsMonitorActive(arrRegKeys(tmpctr)) then
			intArrResultIndex=intArrResultIndex+1
		redim preserve arrResult(intArrResultIndex)
			arrResult(intArrResultIndex)=arrRegKeys(tmpctr)
			'mydebug "ActiveMonitor=" & arrResult(intArrResultIndex)
		end if
	next

	if intArrResultIndex=-1 then
		arrResult(0)="{ERROR}"
		mydebug "ActiveMonitor=Unable to locate any active monitors"
	end if
	GetActiveMonitorsFromAllMonitors=arrResult
End Function

'this function is passed a regsubkey as a string
'and determines if it is an active monitor
'returns boolean
Function IsMonitorActive(strMonitorRegKey)
	dim arrtmpResult
	dim strtmpResult
	arrtmpResult=RegEnumKeys(strMonitorRegKey)
	strtmpResult="|||" & join(arrtmpResult,"|||") & "|||"
	if instr(lcase(strtmpResult),"|||control|||")=0 then
		'mydebug "ActiveMonitorCheck='" & strMonitorRegKey & "' is not active"
		IsMonitorActive=false
	else
		'mydebug "ActiveMonitorCheck='" & strMonitorRegKey & "' is active"
		IsMonitorActive=true
	end if
End Function

'This function is passed an array of regkeys as strings
'and returns an array containing the corresponding contents
'of the EDID value (in string format) for the "Device Parameters" 
'subkey of the specified key
Function GetEDIDFromActiveMonitors(arrRegKeys)
	dim arrResult()
	redim arrResult(0)
	dim intArrResultIndex
	dim tmpctr
	dim strtmpResult
	
	intArrResultIndex=-1
	for tmpctr=0 to ubound(arrRegKeys)
		strtmpResult=GetEDIDForMonitor(arrRegKeys(tmpctr))
		intArrResultIndex=intArrResultIndex+1
		redim preserve arrResult(intArrResultIndex)
		arrResult(intArrResultIndex)=strtmpResult
		'mydebug "GETEDID=" & arrRegKeys(tmpctr) & "EDID,Yes"
	next

	if intArrResultIndex=-1 then
		arrResult(0)="{ERROR}"
		mydebug "EDID=Unable to retrieve any edid"
	end if
	GetEDIDFromActiveMonitors=arrResult
End Function

'given the regkey of a specific monitor
'this function returns the EDID info
'in string format
Function GetEDIDForMonitor(strMonitorRegKey)
	dim arrtmpResult
	dim strtmpResult
	dim bytevalue
	
	arrtmpResult=RegGetBinaryValue(strMonitorRegKey & "\Device Parameters","EDID")
	if vartype(arrtmpResult) <> 8204 then
		mydebug "GetEDID=No EDID Found " & strMonitorRegKey
		GetEDIDForMonitor="{ERROR}"
	else
		for each bytevalue in arrtmpResult
			strtmpResult=strtmpResult & chr(bytevalue)
		next
		'mydebug "GetEDID=EDID Found " & strMonitorRegKey
		'mydebug "GetEDID_Result=" & GetHexFromString(strtmpResult)
		GetEDIDForMonitor=strtmpResult
	end if
End Function

'passed a given string this function 
'returns comma seperated hex values 
'for each byte
Function GetHexFromString(strText)
	dim tmpctr
	dim tmpresult
	
	for tmpctr=1 to len(strText)
		tmpresult=tmpresult & right( "0" & hex(asc(mid(strText,tmpctr,1))),2) & ","
	next
	GetHexFromString=left(tmpresult,len(tmpresult)-1)
End Function

'this function should be passed two arrays with the same
'number of elements. array 1 should contain the
'edid information that corresponds to the active monitor
'regkey found in the same element of array 2
'Why not use a 2D array or a dictionary object?.
'I guess I'm just lazy
Function GetParsedMonitorInfo(arrActiveEDID,arrActiveMonitors)
	dim tmpctr
	dim strSerial
	dim strMfg
	dim strMfgDate
	dim strDev
	dim strModel
	dim strEDIDVer
	dim strWinVesaID
	dim strWinPNPID
	dim arrResult()
	for tmpctr=0 to ubound(arrActiveEDID)
		strSerial=GetSerialFromEDID(arrActiveEDID(tmpctr))
		strMfg=GetMfgFromEDID(arrActiveEDID(tmpctr))
		strMfgDate=GetMfgDateFromEDID(arrActiveEDID(tmpctr))
		strDev=GetDevFromEDID(arrActiveEDID(tmpctr))
		strModel=GetModelFromEDID(arrActiveEDID(tmpctr))
		strEDIDVer=GetEDIDVerFromEDID(arrActiveEDID(tmpctr))
		strWinVesaID=GetWinVESAIDFromRegKey(arrActiveMonitors(tmpctr))
		strWinPNPID=GetWinPNPFromRegKey(arrActiveMonitors(tmpctr))
		redim preserve arrResult(tmpctr)
		arrResult(tmpctr)=arrResult(tmpctr) & strSerial & "|||"
		arrResult(tmpctr)=arrResult(tmpctr) & strMfg & "|||"
		arrResult(tmpctr)=arrResult(tmpctr) & strMfgDate & "|||"
		arrResult(tmpctr)=arrResult(tmpctr) & strDev & "|||"
		arrResult(tmpctr)=arrResult(tmpctr) & strModel & "|||"
		arrResult(tmpctr)=arrResult(tmpctr) & strEDIDVer & "|||"
		arrResult(tmpctr)=arrResult(tmpctr) & strWinVesaID & "|||"
		arrResult(tmpctr)=arrResult(tmpctr) & strWinPNPID
		'mydebug arrResult(tmpctr)
	next
	GetParsedMonitorInfo=arrResult
End Function

'this is a simple string function to break the VESA monitor ID
'from the registry key
Function GetWinVESAIDFromRegKey(strRegKey)
	dim strtmpResult
	if strRegKey="{ERROR}" then
		GetWinVESAIDFromRegKey="Bad Registry Info"
		exit function
	end if
	strtmpResult=right(strRegKey,len(strRegkey)-len(DISPLAY_REGKEY))
	strtmpResult=left(strtmpResult,instr(strtmpResult,"\")-1) 
	GetWinVESAIDFromRegKey=strtmpResult
End Function

'this is a simple string function to break windows PNP device id
'from the registry key
Function GetWinPNPFromRegKey(strRegKey)
	dim strtmpResult
	if strRegKey="{ERROR}" then
		GetWinPNPFromRegKey="Bad Registry Info"
		exit function
	end if 
	strtmpResult=right(strRegKey,len(strRegkey)-len(DISPLAY_REGKEY))
	strtmpResult=right(strtmpResult,len(strtmpResult)-instr(strtmpResult,"\"))
	GetWinPNPFromRegKey=strtmpResult
End Function

'utilizes the GetDescriptorBlockFromEDID function
'to retrieve the serial number block
'from the EDID data
Function GetSerialFromEDID(strEDID)
	dim strTag
	'a serial number descriptor will start with &H00 00 00 ff
	strTag=chr(&H00) & chr(&H00) & chr(&H00) & chr(&Hff)
	GetSerialFromEDID=GetDescriptorBlockFromEDID(strEDID,strTag)
End Function

'utilizes the GetDescriptorBlockFromEDID function
'to retrieve the model description block
'from the EDID data
Function GetModelFromEDID(strEDID)
	dim strTag
	'a model number descriptor will start with &H00 00 00 fc
	strTag=chr(&H00) & chr(&H00) & chr(&H00) & chr(&Hfc)
	GetModelFromEDID=GetDescriptorBlockFromEDID(strEDID,strTag)
End Function

'This function parses a string containing EDID data
'and returns the information contained in one of the
'4 custom "descriptor blocks" providing the data in the
'block is tagged wit a certain prefix
'if no descriptor is tagged with the specified prefix then
'function returns "Not Present in EDID"
'otherwise it returns the data found in the descriptor
'trimmed of its prefix tag and also trimmed of
'leading NULLs (chr(0)) and trailing linefeeds (chr(10))
Function GetDescriptorBlockFromEDID(strEDID,strTag)
	dim strFoundBlock
	dim strResult
	
	if strEDID="{ERROR}" then
		GetDescriptorBlockFromEDID="Bad EDID"
		exit function
	end if

	'*********************************************************************
	'There are 4 descriptor blocks in edid at offset locations
	'&H36 &H48 &H5a and &H6c each block is 18 bytes long
	'the model and serial numbers are stored in the vesa descriptor
	'blocks in the edid.
	'*********************************************************************
	dim arrDescriptorBlock(3)
	arrDescriptorBlock(0)=mid(strEDID,&H36+1,18)
	arrDescriptorBlock(1)=mid(strEDID,&H48+1,18)
	arrDescriptorBlock(2)=mid(strEDID,&H5a+1,18)
	arrDescriptorBlock(3)=mid(strEDID,&H6c+1,18)

	if instr(arrDescriptorBlock(0),strTag)>0 then
		strFoundBlock=arrDescriptorBlock(0)
	elseif instr(arrDescriptorBlock(1),strTag)>0 then
		strFoundBlock=arrDescriptorBlock(1)
	elseif instr(arrDescriptorBlock(2),strTag)>0 then
		strFoundBlock=arrDescriptorBlock(2)
	elseif instr(arrDescriptorBlock(3),strTag)>0 then
		strFoundBlock=arrDescriptorBlock(3)
	else
		GetDescriptorBlockFromEDID="Not Present in EDID"
		exit function
	end if

	strResult=right(strFoundBlock,14)
	'the data in the descriptor block will either fill the 
	'block completely or be terminated with a linefeed (&h0a)
	if instr(strResult,chr(&H0a))>0 then
		strResult=trim(left(strResult,instr(strResult,chr(&H0a))-1))
	else
		strResult=trim(strResult)
	end if

	'although it is not part of the edid spec (as far as i can tell) it seems as though the
	'information in the descriptor will frequently be preceeded by &H00, this
	'compensates for that
	if left(strResult,1)=chr(0) then strResult=right(strResult,len(strResult)-1)

	GetDescriptorBlockFromEDID=strResult
End Function

'This function parses a string containing EDID data
'and returns the VESA manufacturer ID as a string
'the manufacturer ID is a 3 character identifier
'assigned to device manufacturers by VESA
'I guess that means you're not allowed to make an EDID
'compliant monitor unless you belong to VESA.
Function GetMfgFromEDID(strEDID)
	dim tmpEDIDMfg
	dim Char1
	dim Char2
	dim Char3
	dim Byte1
	dim Byte2
	dim tmpmfg
	
	if strEDID="{ERROR}" then
		GetMfgFromEDID="Bad EDID"
		exit function
	end if

	'the mfg id is 2 bytes starting at EDID offset &H08
	'the id is three characters long. using 5 bits to represent
	'each character. the bits are used so that 1=A 2=B etc..
	'
	'get the data
	tmpEDIDMfg=mid(strEDID,&H08+1,2) 
	Char1=0 : Char2=0 : Char3=0 
	Byte1=asc(left(tmpEDIDMfg,1)) 'get the first half of the string 
	Byte2=asc(right(tmpEDIDMfg,1)) 'get the first half of the string
	'now shift the bits
	'shift the 64 bit to the 16 bit
	if (Byte1 and 64) > 0 then Char1=Char1+16 
	'shift the 32 bit to the 8 bit
	if (Byte1 and 32) > 0 then Char1=Char1+8 
	'etc....
	if (Byte1 and 16) > 0 then Char1=Char1+4 
	if (Byte1 and 8) > 0 then Char1=Char1+2 
	if (Byte1 and 4) > 0 then Char1=Char1+1 

	'the 2nd character uses the 2 bit and the 1 bit of the 1st byte
	if (Byte1 and 2) > 0 then Char2=Char2+16 
	if (Byte1 and 1) > 0 then Char2=Char2+8 
	'and the 128,64 and 32 bits of the 2nd byte
	if (Byte2 and 128) > 0 then Char2=Char2+4 
	if (Byte2 and 64) > 0 then Char2=Char2+2 
	if (Byte2 and 32) > 0 then Char2=Char2+1 

	'the bits for the 3rd character don't need shifting
	'we can use them as they are
	Char3=Char3+(Byte2 and 16) 
	Char3=Char3+(Byte2 and 8) 
	Char3=Char3+(Byte2 and 4) 
	Char3=Char3+(Byte2 and 2) 
	Char3=Char3+(Byte2 and 1) 
	tmpmfg=chr(Char1+64) & chr(Char2+64) & chr(Char3+64)
	GetMfgFromEDID=tmpmfg
End Function

'This function parses a string containing EDID data
'and returns the manufacture date in mm/yyyy format
Function GetMfgDateFromEDID(strEDID)
	dim tmpmfgweek
	dim tmpmfgyear
	dim tmpmdt
	
	if strEDID="{ERROR}" then
		GetMfgDateFromEDID="Bad EDID"
		exit function
	end if

	'the week of manufacture is stored at EDID offset &H10
	tmpmfgweek=asc(mid(strEDID,&H10+1,1))

	'the year of manufacture is stored at EDID offset &H11
	'and is the current year -1990
	tmpmfgyear=(asc(mid(strEDID,&H11+1,1)))+1990

	'store it in month/year format 
	tmpmdt=month(dateadd("ww",tmpmfgweek,datevalue("1/1/" & tmpmfgyear))) & "/" & tmpmfgyear
	GetMfgDateFromEDID=tmpmdt
End Function

'This function parses a string containing EDID data
'and returns the device ID as a string
Function GetDevFromEDID(strEDID)
	Dim tmpEDIDDev1
	dim tmpEDIDDev2
	dim tmpdev
	if strEDID="{ERROR}" then
		GetDevFromEDID="Bad EDID"
		exit function
	end if
	'the device id is 2bytes starting at EDID offset &H0a
	'the bytes are in reverse order.
	'this code is not text. it is just a 2 byte code assigned
	'by the manufacturer. they should be unique to a model
	tmpEDIDDev1=hex(asc(mid(strEDID,&H0a+1,1)))
	tmpEDIDDev2=hex(asc(mid(strEDID,&H0b+1,1)))
	if len(tmpEDIDDev1)=1 then tmpEDIDDev1="0" & tmpEDIDDev1
	if len(tmpEDIDDev2)=1 then tmpEDIDDev2="0" & tmpEDIDDev2
	tmpdev=tmpEDIDDev2 & tmpEDIDDev1
	GetDevFromEDID=tmpdev
End Function

'This function parses a string containing EDID data
'and returns the EDID version number as a string
'I should probably do this first and then not return any other data
'if the edid version exceeds 1.3 since most if this code probably
'won't work right if they change the spec drastically enough (which they probably
'won't do for backward compatability reasons thus negating my need to check and
'making this comment somewhat redundant)
Function GetEDIDVerFromEDID(strEDID)
	dim tmpEDIDMajorVer
	dim tmpEDIDRev
	dim tmpver
	
	if strEDID="{ERROR}" then
		GetEDIDVerFromEDID="Bad EDID"
		exit function
	end if

	'the version is at EDID offset &H12
	tmpEDIDMajorVer=asc(mid(strEDID,&H12+1,1))

	'the revision level is at EDID offset &H13
	tmpEDIDRev=asc(mid(strEDID,&H13+1,1))

	tmpver=chr(48+tmpEDIDMajorVer) & "." & chr(48+tmpEDIDRev)
	GetEDIDVerFromEDID=tmpver
End Function

'simple function to provide an
'easier interface to the wmi registry functions
Function RegEnumKeys(RegKey)
	dim hive
	dim strKeyPath
	dim objReg
	dim arrSubKeys
	
	hive=SetHive(RegKey)
	set objReg=GetWMIRegProvider()
	strKeyPath = right(RegKey,len(RegKey)-instr(RegKey,"\"))
	objReg.EnumKey Hive, strKeyPath, arrSubKeys
	RegEnumKeys=arrSubKeys
End Function

'simple function to provide an
'easier interface to the wmi registry functions
Function RegGetStringValue(RegKey,RegValueName)
	dim hive
	dim strKeyPath
	dim tmpreturn
	
	hive=SetHive(RegKey)
	set objReg=GetWMIRegProvider()
	strKeyPath = right(RegKey,len(RegKey)-instr(RegKey,"\"))
	tmpreturn=objReg.GetStringValue(Hive, strKeyPath, RegValueName, RegValue)
	if tmpreturn=0 then
		RegGetStringValue=RegValue
	else
		RegGetStringValue="~{{<ERROR>}}~"
	end if
End Function

'simple function to provide an
'easier interface to the wmi registry functions
Function RegGetMultiStringValue(RegKey,RegValueName)
	dim hive
	dim strKeyPath
	dim tmpreturn
	dim objReg
	dim RegValue
	
	hive=SetHive(RegKey)
	set objReg=GetWMIRegProvider()
	strKeyPath = right(RegKey,len(RegKey)-instr(RegKey,"\"))
	tmpreturn=objReg.GetMultiStringValue(Hive, strKeyPath, RegValueName, RegValue)
	if tmpreturn=0 then
		RegGetMultiStringValue=RegValue
	else
		RegGetMultiStringValue="~{{<ERROR>}}~"
	end if
End Function

'simple function to provide an
'easier interface to the wmi registry functions
Function RegGetBinaryValue(RegKey,RegValueName)
	dim hive
	dim strKeyPath
	dim tmpreturn
	dim objReg
	dim RegValue
	
	hive=SetHive(RegKey)
	set objReg=GetWMIRegProvider()
	strKeyPath = right(RegKey,len(RegKey)-instr(RegKey,"\"))
	tmpreturn=objReg.GetBinaryValue(Hive, strKeyPath, RegValueName, RegValue)
	if tmpreturn=0 then
		RegGetBinaryValue=RegValue
	else
		RegGetBinaryValue="~{{<ERROR>}}~"
	end if
End Function

'simple function to provide a wmi registry provider
'to all the other registry functions (regenumkeys, reggetstringvalue, etc...)
Function GetWMIRegProvider()
	dim strcomputer
	strComputer = "."
	Set GetWMIRegProvider=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")
End Function


Dim strHive
'function to parse the specified hive
'from the registry functions above
'to all the other registry functions (regenumkeys, reggetstringvalue, etc...)
Function SetHive(RegKey)
	const HKEY_CLASSES_ROOT=&H80000000
	const HKEY_CURRENT_USER=&H80000001
	const HKEY_CURRENT_CONFIG=&H80000005
	const HKEY_LOCAL_MACHINE=&H80000002
	const HKEY_USERS=&H80000003
	strHive=left(RegKey,instr(RegKey,"\"))
	if strHive="HKCR\" or strHive="HKR\" then SetHive=HKEY_CLASSES_ROOT
	if strHive="HKCU\" then SetHive=HKEY_CURRENT_USER
	if strHive="HKCC\" then SetHive=HKEY_CURRENT_CONFIG
	if strHive="HKLM\" then SetHive=HKEY_LOCAL_MACHINE
	if strHive="HKU\" then SetHive=HKEY_USERS
End Function

'this sub forces execution under cscript
'it can be useful for debugging if your machine's
'default script engine is set to wscript
Sub ForceCScript
	dim strCurrScriptHost
	dim objFSO
	dim objShell
	dim objArgs
	dim strExecCmdLine
	dim argctr
	dim strExecAllArgs
	dim strExecArg
	
	strCurrScriptHost=lcase(right(wscript.fullname,len(wscript.fullname)-len(wscript.path)-1))
	if strCurrScriptHost<>"cscript.exe" then
		set objFSO=CreateObject("Scripting.FileSystemObject")
		Set objShell = CreateObject("WScript.Shell")
		Set objArgs = WScript.Arguments
		strExecCmdLine=wscript.path & "\cscript.exe //nologo " & objfso.getfile(wscript.scriptfullname).shortpath
	For argctr = 0 to objArgs.Count - 1
		strExecArg=objArgs(argctr)
		if instr(strExecArg," ")>0 then strExecArg=chr(34) & strExecArg & chr(34)
		strExecAllArgs=strExecAllArgs & " " & strExecArg
	Next
	objShell.run strExecCmdLine & strExecAllArgs,1,false
	set objFSO = nothing
	Set objShell = nothing
	Set objArgs = nothing
	wscript.quit
	end if
End Sub

'allows for a pause at the end of execution
'currently used only for debugging
Sub Pause
	dim objStdin
	dim objStdout
	dim strtmp
	
	set objStdin=wscript.stdin
	set objStdout=wscript.stdout
	objStdout.write "Press ENTER to continue..."
	strtmp=objStdin.readline
end Sub

'if debugmode=1 the writes dubug info to the specified
'file and if running under cscript also writes it to screen.
Sub debugout(strDebugInfo)
	dim strCurrScriptHost
	dim objDebugFSO
	dim objDebugStream
	
	if DEBUGMODE=0 then exit sub
	strCurrScriptHost=lcase(right(wscript.fullname,len(wscript.fullname)-len(wscript.path)-1))
	if strCurrScriptHost="cscript.exe" then wscript.echo WScript.ScriptFullName & "::" & "Debug: " & strDebugInfo
	const AppendFileMode=8
	set objDebugFSO=CreateObject("Scripting.FileSystemObject")
	set objDebugStream=objDebugFSO.OpenTextFile(DEBUGFILE,AppendFileMode,True,False)
	objDebugStream.writeline strDebugInfo
	objDebugStream.Close
	set objDebugStream=Nothing
	set objDebugFSO=Nothing
End Sub 

'' SIG '' Begin signature block
'' SIG '' MIID6AYJKoZIhvcNAQcCoIID2TCCA9UCAQExDjAMBggq
'' SIG '' hkiG9w0CBQUAMGYGCisGAQQBgjcCAQSgWDBWMDIGCisG
'' SIG '' AQQBgjcCAR4wJAIBAQQQTvApFpkntU2P5azhDxfrqwIB
'' SIG '' AAIBAAIBAAIBAAIBADAgMAwGCCqGSIb3DQIFBQAEEM94
'' SIG '' ZUoLwXMcEuMnSpRlRvagggISMIICDjCCAXegAwIBAgIQ
'' SIG '' fduYp37PJolB2l4qUoy9tjANBgkqhkiG9w0BAQQFADAV
'' SIG '' MRMwEQYDVQQDEwplLW52ZW50b3J5MB4XDTEwMTIzMTIz
'' SIG '' MDAwMFoXDTE2MTIzMTIzMDAwMFowFTETMBEGA1UEAxMK
'' SIG '' ZS1udmVudG9yeTCBnzANBgkqhkiG9w0BAQEFAAOBjQAw
'' SIG '' gYkCgYEAxoqL8otb0bZl/B6QNeNKa7wgv9FzkgeuH0/K
'' SIG '' Mqta3uf+k/JJF0eRdm/e+R17t2Fy0nn4kkfK/0339ZKA
'' SIG '' j+LrC6N0Z2XzotG2Tf5CR2XYHwGWtXvL1edczqrPEwnJ
'' SIG '' Bep8Fki6p0/CSSFueWSjRmMr3nP5+PNnMWarU/OyVdep
'' SIG '' yDMCAwEAAaNfMF0wEwYDVR0lBAwwCgYIKwYBBQUHAwMw
'' SIG '' RgYDVR0BBD8wPYAQlJeutLm/XtOFAEGETQ1/HKEXMBUx
'' SIG '' EzARBgNVBAMTCmUtbnZlbnRvcnmCEH3bmKd+zyaJQdpe
'' SIG '' KlKMvbYwDQYJKoZIhvcNAQEEBQADgYEAKFw68m9BqK1a
'' SIG '' mJUm2YxwCsT3mWy4nilgTWlC+wj64jouYVSY1Ozhm7L8
'' SIG '' ALBzVvvFCeHMHmvpN4pZdqzAf9CnTcNWPkYBq5Hep2aM
'' SIG '' by6t/JiG9lPhC327WWW5IQV3T+FtK2G1qW9UMGi83PMV
'' SIG '' FhUJeBp5hhxXhWORlcBZg5aiVpgxggFAMIIBPAIBATAp
'' SIG '' MBUxEzARBgNVBAMTCmUtbnZlbnRvcnkCEH3bmKd+zyaJ
'' SIG '' QdpeKlKMvbYwDAYIKoZIhvcNAgUFAKBsMBAGCisGAQQB
'' SIG '' gjcCAQwxAjAAMBkGCSqGSIb3DQEJAzEMBgorBgEEAYI3
'' SIG '' AgEEMBwGCisGAQQBgjcCAQsxDjAMBgorBgEEAYI3AgEV
'' SIG '' MB8GCSqGSIb3DQEJBDESBBDyUrJbwkfYT31tN7VOCdai
'' SIG '' MA0GCSqGSIb3DQEBAQUABIGAoTOiSUFaUQHT0/Q7BeVk
'' SIG '' AsaJsxHp44QDFyT+7VHzVavJ8k92wNJ72a4GCJ3Gty6f
'' SIG '' tfGNpMTqsnGQgdk9ukYSm6usmBY8ykVu7FhcaR73IV58
'' SIG '' z0cgcdub64Oq9NuGzBBF1FJ6xjp1teHUx8VQ6k9pFmYQ
'' SIG '' 7HFd051JMpUR6j1ahRs=
'' SIG '' End signature block
